<?php
namespace service;
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2018/11/2
 * Time: 23:52
 */
use \GatewayWorker\Lib\Gateway;
include_once ROOT_PATH.'/ws/service/JWT.php';
use jwt\JWT;
class ChatNewService
{
    //用户所在组
    static protected $group= '_chat_new_';
    //所有用户信息（哈希）[ uid1=>userinfo,uid2=>userinfo]
    static protected $user_info='_chat_new_hash_user_info';
    //在线用户（合集）[uid1,uid2,uid4]
    static protected $user_online='_chat_new_set_user_online';
    //用户关系表（好友列表）前缀 +uid （有序合合集）,根据用户发送信息先后，排序
    static protected $user_relation='_chat_new_sorted_user_relation_';
    //用户关系 [ 请求 ]  表前缀 +uid （哈希）一个用户对应一个表，一个请求用户对应一个field，请求容对应value
    static protected $user_request='_chat_new_hash_user_request_';
    //用户系统消息表前缀 +uid (列表) 只保存10条消息
    static protected $user_system='_chat_new_list_user_system_';
    //群聊房间信息表格文件名
    static protected $chat_group_room='chat_group_room';
    //群聊消息（合集）[msg1,msg2,msg3]
    static protected $group_chat='_chat_new_set_group_chat';
    //聊天室信息（哈希）？？？
    static protected $chat_room='';
    //私聊保存前缀 send_id + receive_id（合集）
    static protected $private_group_list='_chat_new_list_private_chat_';


    /**
     * 用户初始连接时
     * $_SESSION 会保存存用户ID
     * */
    public  static function onWebSocketConnect($client_id,$data ,$db,$redis)
    {

    }

    /**
     * 用户初始连接时
     * $_SESSION 会保存存用户ID
     * */
    public static function onOpen($client_id,$data ,$db,$redis)
    {
        $isauth=false;//是否进行用户鉴权，为TRUE不进行鉴权，为FALSE时进行用户鉴权
        $_SESSION['class']=__CLASS__;
        if( empty($data['user_info']) ||  empty($data['user_info']['id']) ){
            return self::error($client_id,'传入数据不全',$data);
        }
        if(!$isauth){
            $chat=$db->select('*')->from('chat_user')->where('id='.$data['user_info']['id'])->row();
            if(empty($chat['token'])){
                return self::error($client_id,'查询不到token，请重新登录后连接',$data);
            }
            $toke=$chat['token'];
            $jwt=self::jwtDecode($data['token'],$toke,$client_id);
            if(!$jwt){
                return self::error($client_id,'解码失败，请重新登录后连接',$data);
            }
            foreach ($jwt['data'] as $key=>$item){
                if( $chat[$key] =$item){
                    $auth =true;
                    break;
                }
            }
        }
        if($isauth || $auth){
            $id=self::$group.(string)$data['user_info']['id'];
            $_SESSION['id']=$id;
            Gateway::bindUid($client_id,$id);
            $redis->hSet(self::$user_info,$id,json_encode($data['user_info'],320));//用户信息存入哈希
            $redis->sAdd(self::$user_online,$id);//在线用户存入合集
            $data['type']='receiveChatOnOpen';
            Gateway::joinGroup($client_id, self::$group);
            if(isset($data['token'])){ unset($data['token']); }
            if(isset($data['exp'])){  unset($data['exp']); }
            Gateway::sendToGroup(self::$group,json_encode($data,320));//所有人广播上线
            Gateway::sendToClient($client_id,json_encode(['type'=>'receiveChatOnLine'],320));//告知自己上线成功
        }else{
            self::error($client_id,'登录鉴权失败',$data);
        }
    }

    /**
     * 用户关闭时
     * */
    public static function onClose($client_id,$db,$redis)
    {
        if( isset( $_SESSION['id']) && isset( $_SESSION['class']) &&   $_SESSION['class'] === __CLASS__){
            $arr=Gateway::getClientIdByUid($_SESSION['id']);
            if(count($arr) === 0){
                $new_data['type']='receiveLogOut';
                $new_data['id']=$_SESSION['id'];
                Gateway::sendToGroup(self::$group,json_encode($new_data,320));
            }
        }
    }
    /**
     * 用户主动注销
     * */
    public static function loginOut($client_id,$data ,$db,$redis)
    {
        if(empty($_SESSION['id'])){
            return Gateway::closeClient($client_id);
        }
        $id=$_SESSION['id'];
        $arr=Gateway::getClientIdByUid($id);
        $new_data['type']='receiveChatOffLine';
        if(count($arr) === 1){
            $redis->srem(self::$user_online,$id);//在线用户存入移出
            Gateway::sendToClient($client_id,json_encode($new_data,320));
        }
        unset($_SESSION['id']);
        unset($_SESSION['class']);
    }

    /**
     * 取得好友列表
     * */
    public static function getRelation($client_id,$data ,$db,$redis)
    {
        if(empty($_SESSION['id']) || $_SESSION['id']!==self::$group.$data['send_id']){
            return self::error($client_id,'请求用户信息不准确',$data);
        }
        $user_list=$redis->zRange(self::$user_relation.$data['send_id'],0,-1);
        if(count($user_list)===0){
            return self::error($client_id,'好友列表为空',$data);
        }
        $user_list=$redis->hmGet(self::$user_info,$user_list);
        $user_list=array_map(function ($item){
            if(is_string($item)){
                $item=json_decode($item,true);
            }
            return $item;
        },$user_list);
        $arr['user_list']=array_values($user_list);
        $arr['type']='receiveGetRelation';
        Gateway::sendToUid($_SESSION['id'],json_encode($arr,320));
    }

    /*
     * 获取在线成员列表信息
     * */
    public static function getOnlineUser($client_id,$data ,$db,$redis)
    {
        $user_list=Gateway::getUidListByGroup(self::$group);
        $user_list=$redis->hmGet(self::$user_info,$user_list);
        $user_list=array_map(function ($item){
            if(is_string($item)){
                $item=json_decode($item,true);
            }
            return $item;
        },$user_list);
        $arr['user_list']=array_values($user_list);
        $arr['type']='receiveGetOnlineUser';
        Gateway::sendToUid($_SESSION['id'],json_encode($arr,320));
    }
    /**
     * 请求添加好友列表
     * */
    public static function requestRelation($client_id,$data ,$db,$redis)
    {
        if(empty($data['send_id']) || empty( $data['receive_id'])){//用户传入发送者ID和接收方ID，
            return self::error($client_id,'没有传入用户ID',$data);
        }
        $data['message']=empty($data['message'])?'请求添加好友' : $data['message'];
        $redis->hSet(self::$user_request.$data['receive_id']  ,  self::$group.$data['send_id']  ,  $data['message']);
        $data['type']='receiveRequestRelation';
        Gateway::sendToUid(self::$group.$data['receive_id'],json_encode($data,320));
    }

    /**
     * 取得请求列表
     * */
    public static function getRequestRelation($client_id,$data ,$db,$redis)
    {
        if(empty($data['send_id']) ){//用户传入发送者ID和接收方ID，
            return self::error($client_id,'没有传入用户ID',$data);
        }
        $request=$redis->hGetAll(self::$user_request.$data['send_id']);//取得所有请求列表
        if(count($request) === 0){
            return;
        }
        $new_data['type']='receiveRequestRelationList';
        $new_data['list']=$request;
        Gateway::sendToUid(self::$group.$data['send_id'],json_encode($new_data,320));
    }

    /**
     * 处理添加好友 agree同意 refuse 拒绝
     * */
    public static function manageRelation($client_id,$data ,$db,$redis)
    {
        if( empty($data['send_id']) || empty($data['receive_id']) || empty($data['handle']) ){
            return self::error($client_id,'传入ID为空',$data);
        }
        $receive_id=self::$group.$data['receive_id'];
        $send_id=self::$group.$data['send_id'];
        $request=$redis->hGet(self::$user_request.$data['send_id'], $receive_id);//是否存在请求列表
        $redis->hDel(self::$user_request.$data['send_id'],$send_id);//删除请求信息

        if(!$request ){
            return  self::error($client_id,'该请求已处理',$data);
        }
        //忆经在对方好友列表中
        if($redis->zRank(self::$user_relation.$data['send_id'],$receive_id) ){
            return  self::error($client_id,'已经是好友请勿重复添加',$data);
        }
        $time=time();
        $data['time']=$time;
        //用户同意请求
        if($data['handle'] ==='agree' ){
            $redis->zAdd(self::$user_relation.$data['send_id'],$time,self::$group.$data['receive_id']);
            $redis->zAdd(self::$user_relation.$data['receive_id'],$time,self::$group.$data['send_id']);
            $data['send_user_info']=$redis->hGet(self::$user_info,$send_id);
            $data['receive_user_info']=$redis->hGet(self::$user_info,$receive_id);
        }
        $data['type']="receiveManageRelation";
        //做返回处理
        $str=json_encode($data,320);
        Gateway::sendToUid(self::$group.$data['receive_id'],$str);
        Gateway::sendToUid(self::$group.$data['send_id'],$str);
        //写入用户系统消息
        $redis->lPush(self::$user_system.$data['receive_id'],$str);
        $redis->lPush(self::$user_system.$data['send_id'],$str);

    }

    /**
     * 删除好友
     * */
    public static function removeRelation($client_id,$data ,$db,$redis)
    {

    }
    /**
     * 发送给所有人
     * */
    public static function sendToAll($client_id,$data ,$db,$redis)
    {

    }

    /**
     * 取得群聊消息列表
     * */
    public static function getGroupChatList($client_id,$data ,$db,$redis)
    {

    }

    /**
     * 私聊某人
     * */
    public static function sendToUid($client_id,$data ,$db,$redis)
    {
        $send_uid=$data['send_id'];
        $receive_uid=$data['receive_id'];
        $redis_name_to=self::$private_group_list.$send_uid.'_'.$receive_uid;
        $redis_name_from=self::$private_group_list.$receive_uid.'_'.$send_uid;
        $redis_name=$redis->exists($redis_name_to)?$redis_name_to:$redis_name_from;
        $redis->rPush($redis_name,json_encode($data,320));
        $len=$redis->lLen($redis_name);
        if($len>200){
            $redis->ltrim($redis_name,100,200);
            //$db->;数据库操作 待完成
        }
        $redis->expire($redis_name,604800);
        $data['type']='receiveChatPrivate';
        $str=json_encode($data,320);
        Gateway::sendToUid( self::$group.(string)$data['receive_id'] ,$str);
        Gateway::sendToUid( self::$group.(string)$data['send_id'] ,$str);
        
    }

    /**
     * 取得私聊信息
     * */
    public static function getPrivateChat($client_id,$data ,$db,$redis)
    {
        $sendUid=$data['send_id'];
        $receiveUid=$data['receive_id'];
        $redis_name_to=self::$private_group_list.$sendUid.'_'.$receiveUid;
        $redis_name_from=self::$private_group_list.$receiveUid.'_'.$sendUid;
        $redis_name=$redis->exists($redis_name_to)?$redis_name_to:$redis_name_from;
        $data['list'] = $redis->lrange($redis_name, 0, -1);
        $data['type']='receiveChatPrivateList';
        Gateway::sendToUid(self::$group.(string)$data['send_id'],json_encode($data,320));
    }

    /**
     * 获取用户列表
     * */
    public static function getUserList($client_id,$data ,$db,$redis)
    {
        if( isset($_SESSION['id']) ){
            if(empty($data['type'])){
                if(isset($data['online'])){
                    $user_list=Gateway::getUidListByGroup(self::$group);
                }else{
                    $user_list=$redis->sMembers(self::$user_online);
                }
                $arr['type']='receiveChatUserList';
            }else{
                $arr['type']=$data['type'];
                $user_list=isset($data['list'])?$data['list']:null;
            }
            if ( !empty($user_list) ){
                $user_list=$redis->hmGet(self::$user_info,$user_list);
                $user_list=array_map(function ($item){
                    if(is_string($item)){
                        $item=json_decode($item,true);
                    }
                    return $item;
                },$user_list);
                $arr['user_list']=$user_list;
                Gateway::sendToUid($_SESSION['id'],json_encode($arr,320));
            }
        }else{
            Gateway::sendToClient($client_id,json_encode(['type'=>'receiveChatOffLine'],320));
        }
    }

    /**
     * 错误返回
     * */
    private static function error($client_id,$message='',$data=null,$code=4000)
    {
        //echo 'error=============================='.$message,PHP_EOL;
        $data=[
            'type'=>'receiveErrorMessage',
            'code'=>$code,
            'message'=>$message,
            'data'=>$data
        ];
        Gateway::sendToClient($client_id,json_encode($data,320));//告知自己上线成功
    }

    /**
     * 解码JWT信息
     * */
    private static function jwtDecode($jwt, $key,$client_id)
    {
        try{
            $decoded = JWT::decode($jwt, $key, array('HS256'));
            $decoded =(array)$decoded;
            if(empty($decoded['data']) || empty($decoded['exp'])){
                return false;
            }
            $decoded['data']=(array)$decoded['data'];
            return  $decoded;
        }catch (\Exception $e){
            self::error($client_id,'jwt解码失败');
        }
    }


}